package com.yh.csx.bsf.ods.clickhouse;

import java.math.BigDecimal;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.apache.commons.lang3.StringUtils;

import com.yh.csx.bsf.ods.meta.MysqlDataType;

import ru.yandex.clickhouse.domain.ClickHouseDataType;

/**
 * Clickhouse工具类
 * 
 * @author Robin.Wang
 * @date 2020-05-11
 *
 */
public class ClickhouseTypeUtil {

	
	public static Class<?> jdbcType2javaType(int jdbcType) {
		switch (jdbcType) {
		case Types.BIT:
		case Types.BOOLEAN:
			// return Boolean.class;
		case Types.TINYINT:
			return Byte.TYPE;
		case Types.SMALLINT:
			return Short.class;
		case Types.INTEGER:
			return Integer.class;
		case Types.BIGINT:
			return Long.class;
		case Types.DECIMAL:
		case Types.NUMERIC:
			return BigDecimal.class;
		case Types.REAL:
			return Float.class;
		case Types.FLOAT:
		case Types.DOUBLE:
			return Double.class;
		case Types.CHAR:
		case Types.VARCHAR:
		case Types.LONGVARCHAR:
			return String.class;
		case Types.BINARY:
		case Types.VARBINARY:
		case Types.LONGVARBINARY:
		case Types.BLOB:
			return byte[].class;
		case Types.DATE:
			return java.sql.Date.class;
		case Types.TIME:
			return Time.class;
		case Types.TIMESTAMP:
			return Timestamp.class;
		default:
			return String.class;
		}
	}

	/**
	 * 数据类型转换
	 */
	public static ClickHouseDataType mysqlType2ClickhouseType(MysqlDataType jdbcType) {
		switch (jdbcType) {
		case BIT:
		case TINYINT:
			return ClickHouseDataType.Int8;
		case SMALLINT:
			return ClickHouseDataType.Int16;
		case INT:
			return ClickHouseDataType.Int32;
		case BIGINT:
			return ClickHouseDataType.Int64;
		case DECIMAL:
		case NUMERIC:
			return ClickHouseDataType.Decimal;
		case REAL:
		case FLOAT:
			return ClickHouseDataType.Float32;
		case DOUBLE:
			return ClickHouseDataType.Float64;
		
		case CHAR:
		case VARCHAR:
		case VARBINARY:
		case BLOB:
			return ClickHouseDataType.String;
		case DATE:
			return ClickHouseDataType.Date;
		case TIME:
			return ClickHouseDataType.String;
		case TIMESTAMP:
		case DATETIME:
			return ClickHouseDataType.DateTime;
		default:
			return ClickHouseDataType.String;
		}

	}
	/**
	 * 数据类型转换
	 */
	public static ClickHouseDataType jdbcType2ClickhouseType(int jdbcType) {
		switch (jdbcType) {
		case Types.BIT:
			return ClickHouseDataType.Int8;
		case Types.BOOLEAN:
			return ClickHouseDataType.Int8;
		case Types.TINYINT:
			return ClickHouseDataType.Int8;
		case Types.SMALLINT:
			return ClickHouseDataType.Int16;
		case Types.INTEGER:
			return ClickHouseDataType.Int32;
		case Types.BIGINT:
			return ClickHouseDataType.Int64;
		case Types.DECIMAL:
			return ClickHouseDataType.Decimal;
		case Types.NUMERIC:
			return ClickHouseDataType.Decimal;
		case Types.REAL:
			return ClickHouseDataType.Float32;
		case Types.FLOAT:
			return ClickHouseDataType.Float32;
		case Types.DOUBLE:
			return ClickHouseDataType.Float64;
		case Types.CHAR:

		case Types.VARCHAR:
		case Types.LONGVARCHAR:
		case Types.VARBINARY:
		case Types.LONGVARBINARY:
		case Types.BINARY:
		case Types.BLOB:
			return ClickHouseDataType.String;
		case Types.DATE:
			return ClickHouseDataType.Date;
		case Types.TIME:
			return ClickHouseDataType.String;
		case Types.TIMESTAMP:
			return ClickHouseDataType.DateTime;
		default:
			return ClickHouseDataType.String;
		}

	}

	/**
	 * 数据类型转换
	 */
	public static ClickHouseDataType mysqlType2ClickhouseType(String type) {
		return ClickHouseDataType.String;

	}

	/**
	 * 数据类型转换
	 */
	public static Object perseValue(ClickHouseDataType type, Object value) {
		switch (type) {
		case Int8:
		case Int16:
		case Int32:
			if (value == null || StringUtils.isBlank(value.toString()))
				return "";
			if ("TRUE".equals(value.toString().toUpperCase())) {
				return 1;
			}
			if ("FALSE".equals(value.toString().toUpperCase())) {
				return 0;
			}
			return Integer.valueOf(value.toString());
		case Int64:
			if (value == null || StringUtils.isBlank(value.toString()))
				return "";
			return Long.valueOf(value.toString());
		case Decimal:
		case Decimal32:
		case Decimal64:
			return Double.valueOf(value.toString());
		case Float32:
			if (value == null || StringUtils.isBlank(value.toString()))
				return "";
			return Float.valueOf(value.toString());
		case Float64:
			if (value == null || StringUtils.isBlank(value.toString()))
				return "";
			return Double.valueOf(value.toString());
		case FixedString:
		case String:
			if (value == null)
				return "''";
			if (StringUtils.isBlank(value.toString()))
				return "''";
			return "'" + value.toString().replaceAll("\\\\", "\\\\\\\\").replaceAll("\\'", "\\\\'").replaceAll("\\t", "") + "'";
		case Date:
			if (value == null || StringUtils.isBlank(value.toString()))
				return "";
			return "'" + value.toString().replaceAll("\\'", "\\\\'") + "'";

		case DateTime:
			
			if (value == null || StringUtils.isBlank(value.toString()))
				return "";
			String date=value.toString();
			if(date.contains("10000")) {
				date=value.toString().replace("10000", "9999");
			}
			if (value instanceof Date) {
				date=(new SimpleDateFormat("YYYY-MM-dd HH:mm:ss")).format(value);
				date = date.replace("10000-", "9999-");;
				return "'" + date + "'";				
			} else if (value instanceof String) {
				
				Date d = null;
				try {
					d = (new SimpleDateFormat("YYYY-MM-dd HH:mm:ss")).parse(date.replace("\\.*", ""));
				} catch (ParseException e) {
					e.printStackTrace();
				}
				if (d != null) {
					return "'" + (new SimpleDateFormat("YYYY-MM-dd HH:mm:ss")).format(d) + "'";
				} else {
					return "";
				}
			}
			return "'" + (new SimpleDateFormat("YYYY-MM-dd HH:mm:ss")).format(value) + "'";
		default:
			if(value==null)
				return "";
			return "'" + value.toString().replaceAll("\\'", "\\\\'").replace("\\t","") + "'";
		}

	}

	/**
	 * 数据类型转换
	 */
	/*
		 * public static Object perseValue(Object value) { if (value instanceof String)
		 * { if (StringUtils.isBlank(value.toString())) { return "''"; } return "'" +
		 * value.toString().replaceAll("\\'", "\\\\'") + "'"; } if (value instanceof
		 * Number) { return value; } if (value instanceof Boolean) { if ((Boolean)
		 * value) return 1; return 0; } if (value instanceof Date) { return "'" + (new
		 * SimpleDateFormat("YYYY-MM-dd HH:mm:ss").format(value)) + "'"; } if (value
		 * instanceof Time) { return "'" + value.toString().replaceAll("'", "\\'") +
		 * "'"; } if (value == null) { return ""; } return "'" +
		 * value.toString().replaceAll("'", "\\'") + "'";
		 * 
		 * }
		 */

	public static Object jdbcType2SqlValue(int jdbcType, String val) {
		switch (jdbcType) {
		case Types.BIT:
		case Types.BOOLEAN:
		case Types.TINYINT:
		case Types.SMALLINT:
		case Types.INTEGER:
			return StringUtils.isBlank(val) ? 0 : Integer.valueOf(val.toString());
		case Types.BIGINT:
			return StringUtils.isBlank(val) ? 0 : Long.valueOf(val.toString());
		case Types.DECIMAL:
		case Types.NUMERIC:
			return StringUtils.isBlank(val) ? 0 : val;
		case Types.REAL:
		case Types.FLOAT:
			return StringUtils.isBlank(val) ? 0 : Float.valueOf(val.toString());
		case Types.DOUBLE:
			return StringUtils.isBlank(val) ? 0 : Double.valueOf(val.toString());
		case Types.CHAR:
		case Types.VARCHAR:
		case Types.LONGVARCHAR:
		case Types.BINARY:
		case Types.VARBINARY:
		case Types.LONGVARBINARY:
		case Types.BLOB:
			return "'" + val.replaceAll("\\'", "\\\\'").replaceAll("\\t", "") + "'";
		case Types.DATE:
		case Types.TIME:
		case Types.TIMESTAMP:
		default:
			return "'" + val + "'";
		}

	}
}
